import 'dart:convert';
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_hanzi/src/hanzi_transform.dart';

import 'hanzi_painter.dart';

enum HanziAniType {
  ///无动画
  none,

  ///一次一个笔划
  stroke,

  /// 一次全画完
  once,
  /// 循环
  loop,
}


class HanziWidget extends StatelessWidget {
  ///动画类型
  final HanziAniType animationType;

  ///汉字颜色
  final Color color;

  ///汉字背景颜色 不设置不显示背景
  final Color? backgroundColor;

  ///汉字数据
  final String? chineseData;

  ///写第几笔
  final int? strokeIndex;

  const HanziWidget({
    super.key,
    required this.chineseData,
    this.color = Colors.black,
    this.animationType = HanziAniType.once,
    this.backgroundColor,
    this.strokeIndex,
  });

  @override
  Widget build(BuildContext context) {
    if (chineseData == null) {
      return const SizedBox();
    }
    return LayoutBuilder(builder: (context, constraints) {
      var json = jsonDecode(chineseData!);
      double scale = min(constraints.maxWidth, constraints.maxHeight) / 1024;
      HanziTransform.transformData(json, scale: scale);
      var pathList = HanziTransform.transformStrokePathList(json);
      var metricList = HanziTransform.transformMetricList(json);
      return Stack(
        children: [
          if (backgroundColor != null)
            CustomPaint(
              painter: HanziPainter(
                  strokePathList: pathList,
                  metricList: metricList,
                  scale: scale,
                  color: backgroundColor,
                  animationType: HanziAniType.none),
            ),
          HanziAnimation(
            key: ValueKey([strokeIndex, animationType]),
            strokePathList: pathList,
            metricList: metricList,
            scale: scale,
            color: color,
            animationType: animationType,
            strokeIndex: strokeIndex,
          ),
        ],
      );
    });
  }
}

class HanziAnimation extends StatefulWidget {
  ///动画类型
  final HanziAniType animationType;

  ///汉字颜色
  final Color color;

  ///写第几笔
  final int? strokeIndex;
  final double scale;

  final List<PathMetric> metricList;
  final List<Path> strokePathList;

  const HanziAnimation(
      {super.key,
      required this.metricList,
      required this.strokePathList,
      required this.color,
      required this.scale,
      this.animationType = HanziAniType.once,
      this.strokeIndex});

  @override
  State<HanziAnimation> createState() => _HanziAnimationState();
}

class _HanziAnimationState extends State<HanziAnimation> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;
  int mStrokeIndex = 0;

  @override
  void initState() {
    if (widget.animationType == HanziAniType.stroke) {
      mStrokeIndex = widget.strokeIndex ?? 0;
      if (mStrokeIndex < 0) {
        mStrokeIndex = 0;
      } else if (mStrokeIndex > widget.metricList.length - 1) {
        mStrokeIndex = widget.metricList.length - 1;
      }
    }
    _controller = AnimationController(vsync: this, duration: getStrokeDuration());
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller);
    _controller.addStatusListener(_statusListener);
    if (widget.animationType != HanziAniType.none) {
      _controller.forward();
    }
    super.initState();
  }

  void _statusListener(AnimationStatus status) {
    if (status == AnimationStatus.completed) {
      if ((widget.animationType == HanziAniType.once && mStrokeIndex < widget.metricList.length - 1) || widget.animationType == HanziAniType.loop) {
        mStrokeIndex++;
        if (mStrokeIndex >= widget.metricList.length){
          mStrokeIndex = 0;
        }
        _controller.duration = getStrokeDuration();
        Future.delayed(const Duration(milliseconds: 100), () {
          if (mounted){
            setState(() {
              _controller.reset();
              _controller.forward();
            });
          }
        });
      }
    }
  }

  Duration getStrokeDuration() {
    double length = widget.metricList[mStrokeIndex].length;
    return Duration(milliseconds: length / widget.scale * 1000 ~/ 500);
  }

  @override
  void dispose() {
    _controller.removeStatusListener(_statusListener);
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: HanziPainter(
          repaint: _animation,
          metricList: widget.metricList,
          strokePathList: widget.strokePathList,
          scale: widget.scale,
          animationType: widget.animationType,
          color: widget.color,
          strokeIndex: mStrokeIndex),
    );
  }
}

